package com.wuhunyu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wuhunyu.client.OrderServiceClient;
import com.wuhunyu.client.VideoServiceClient;
import com.wuhunyu.commonutils.check.Check;
import com.wuhunyu.commonutils.jwt.JwtUtils;
import com.wuhunyu.commonutils.result.CommonResult;
import com.wuhunyu.entities.*;
import com.wuhunyu.entities.vo.CourseDetailVo;
import com.wuhunyu.entities.vo.CourseInfoVo;
import com.wuhunyu.entities.vo.CourseVo;
import com.wuhunyu.enums.CourseStatus;
import com.wuhunyu.mapper.*;
import com.wuhunyu.query.EduCourseQuery;
import com.wuhunyu.service.EduChapterService;
import com.wuhunyu.service.EduCourseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wuhunyu.service.EduVideoService;
import com.wuhunyu.servicebase.exception.Assert;
import com.wuhunyu.utils.PageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * 课程 服务实现类
 *
 * @author wuhunyu
 * @since 2021-01-17
 */
@Service("eduCourseService")
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {

    /**
     * 讲师mapper
     */
    @Resource
    private EduTeacherMapper eduTeacherMapper;

    /**
     * 课程mapper
     */
    @Resource
    private EduCourseMapper eduCourseMapper;

    /**
     * 课程分类mapper
     */
    @Resource
    private EduSubjectMapper subjectMapper;

    /**
     * 课程章节mapper
     */
    @Resource
    private EduChapterMapper eduChapterMapper;

    /**
     * 课程小节mapper
     */
    @Resource
    private EduVideoMapper eduVideoMapper;

    /**
     * 课程描述信息
     */
    @Resource
    private EduCourseDescriptionMapper eduCourseDescriptionMapper;

    /**
     * 课程小节mapper
     */
    @Autowired
    private EduVideoService eduVideoService;

    @Autowired
    private VideoServiceClient videoServiceClient;

    @Autowired
    private EduChapterService eduChapterService;

    @Autowired
    private OrderServiceClient orderServiceClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult addCourse(CourseInfoVo courseInfoVo) {
        // 校验参数
        // 课程id为空
        Assert.isRight(Check.isNotBlank(courseInfoVo.getCourseId()), "新增课程信息id必须为空");

        // 公共校验方法
        EduSubject eduSubject = this.commonCheck(courseInfoVo);

        // 课程标题不能重复
        QueryWrapper<EduCourse> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("title", courseInfoVo.getTitle());
        Assert.isRight(eduCourseMapper.selectCount(queryWrapper) >= 1, "课程标题已存在");
        // 课程描述信息是否已存在
        Assert.isRight(Check.isNotBlank(eduCourseDescriptionMapper.selectById(courseInfoVo.getCourseId())), "课程描述已存在");

        // 执行添加操作
        // 添加课程信息
        EduCourse eduCourse = new EduCourse(null,
                courseInfoVo.getTeacherId(),
                courseInfoVo.getSubjectId(),
                eduSubject.getParentId(),
                courseInfoVo.getTitle(),
                courseInfoVo.getPrice(),
                courseInfoVo.getLessonNum(),
                courseInfoVo.getCover(),
                0L,
                0L,
                0L,
                CourseStatus.valueOf("draft").getStatus(),
                0,
                null,
                null);
        Assert.isRight(eduCourseMapper.insert(eduCourse) != 1, "课程信息插入失败");

        // 添加课程描述信息
        Assert.isRight(eduCourseDescriptionMapper.insert(
                new EduCourseDescription(
                        eduCourse.getId(),
                        courseInfoVo.getDescription(),
                        null,
                        null)) != 1
                , "课程描述信息插入失败");
        // 结果需要返回添加课程后的课程id
        Map<String, Object> map = new HashMap<>(16);
        map.put("courseId", eduCourse.getId());
        return CommonResult.success("课程添加成功", map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult deleteCourse(String id) {
        // 校验id
        Assert.isRight(Check.isBlank(id), "课程id不能为空");
        // 删除课程描述信息
        if (Check.isNotBlank(eduCourseDescriptionMapper.selectById(id))) {
            Assert.isRight(eduCourseDescriptionMapper.deleteById(id) != 1, "课程描述信息删除失败");
        }
        // 删除章节信息
        QueryWrapper<EduChapter> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("course_id", id);
        if (eduChapterMapper.selectCount(queryWrapper1) > 0) {
            HashMap<String, Object> map = new HashMap<>(16);
            map.put("course_id", id);
            Assert.isRight(eduChapterMapper.deleteByMap(map) <= 0, "章节信息删除失败");
        }
        // 删除小节信息
        QueryWrapper<EduVideo> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("course_id", id);
        List<EduVideo> eduVideos = eduVideoMapper.selectList(queryWrapper2);
        ArrayList<String> ids = new ArrayList<>();
        if (Check.isNotBlank(eduVideos)) {
            eduVideos.forEach(video -> {
                if (Check.isNotBlank(video.getVideoSourceId())) {
                    ids.add(video.getVideoSourceId());
                }
            });
            if (Check.isNotBlank(ids)) {
                // 批量删除视频
                videoServiceClient.deleteVideos(ids);
            }
        }
        // 查询课程是否存在,课程存在则执行删除
        if (Check.isNotBlank(eduCourseMapper.selectById(id))) {
            Assert.isRight(eduCourseMapper.deleteById(id) != 1, "课程删除失败");
        }
        return CommonResult.success("课程信息删除成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult updateCourse(CourseInfoVo courseInfoVo) {
        // 校验参数
        // 课程id不能为空
        Assert.isRight(Check.isBlank(courseInfoVo.getCourseId()), "修改课程信息id不能为空");

        // 公共校验方法
        EduSubject eduSubject = this.commonCheck(courseInfoVo);

        // 标题不能重复，但可以和自己相同
        QueryWrapper<EduCourse> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("title", courseInfoVo.getTitle());
        queryWrapper.ne("id", courseInfoVo.getCourseId());
        Assert.isRight(eduCourseMapper.selectCount(queryWrapper) >= 1, "课程标题已存在");
        // 课程描述信息是否已存在
        Assert.isRight(Check.isBlank(eduCourseDescriptionMapper.selectById(courseInfoVo.getCourseId())), "课程描述异常");

        // 执行修改操作
        // 修改课程信息
        EduCourse eduCourse = new EduCourse(courseInfoVo.getCourseId(),
                courseInfoVo.getTeacherId(),
                courseInfoVo.getSubjectId(),
                eduSubject.getParentId(),
                courseInfoVo.getTitle(),
                courseInfoVo.getPrice(),
                courseInfoVo.getLessonNum(),
                courseInfoVo.getCover(),
                0L,
                0L,
                null,
                CourseStatus.valueOf("draft").getStatus(),
                0,
                null,
                null);
        Assert.isRight(eduCourseMapper.updateById(eduCourse) != 1, "课程信息修改失败");

        // 修改课程描述信息
        Assert.isRight(eduCourseDescriptionMapper.updateById(
                new EduCourseDescription(
                        eduCourse.getId(),
                        courseInfoVo.getDescription(),
                        null,
                        null)) != 1
                , "课程描述信息修改失败");
        // 结果需要返回修改课程后的课程id
        Map<String, Object> map = new HashMap<>(16);
        map.put("courseId", eduCourse.getId());
        return CommonResult.success("课程修改成功", map);
    }

    /**
     * 新增和修改公用参数校验
     * @param courseInfoVo
     */
    public EduSubject commonCheck(CourseInfoVo courseInfoVo) {
        // 讲师id
        Assert.isRight(Check.isBlank(courseInfoVo.getTeacherId()), "课程讲师id不能为空");
        // 课程专业id
        Assert.isRight(Check.isBlank(courseInfoVo.getSubjectId()), "课程专业id不能为空");
        // 课程标题不能为空
        Assert.isRight(Check.isBlank(courseInfoVo.getTitle()), "课程标题不能为空");
        // 课程销售价格不能为空，且大于等于0
        Assert.isRight(courseInfoVo.getPrice() == null || (courseInfoVo.getPrice().compareTo(new BigDecimal(0)) == -1), "课程价格不能为空");
        // 总课时不能为空，且大于等于0
        Assert.isRight(courseInfoVo.getLessonNum() == null || courseInfoVo.getLessonNum() < 0, "总课时不能为空");
        // 课程封面不能为空
        Assert.isRight(Check.isBlank(courseInfoVo.getCover()), "课程封面不能为空");
        // 课程简介不能为空
        Assert.isRight(Check.isBlank(courseInfoVo.getDescription()), "课程简介不能为空");
        // 参数真实性校验
        // 讲师是否存在
        Assert.isRight(Check.isBlank(eduTeacherMapper.selectById(courseInfoVo.getTeacherId())), "讲师不存在");
        // 课程所属分类是否存在
        EduSubject eduSubject = subjectMapper.selectById(courseInfoVo.getSubjectId());
        Assert.isRight(Check.isBlank(eduSubject), "课程所属分类不存在");
        return eduSubject;
    }

    @Override
    public CommonResult selectCourseInfo(String courseId) {
        // 校验参数
        Assert.isRight(Check.isBlank(courseId), "课程id不能为空");
        // 执行查询操作
        Map<String, Object> map = eduCourseMapper.selectCourseInfo(courseId);
        // 校验结果集，一共八个
        Assert.isRight(map.size() != 8, "查询课程信息失败");
        // 返回结果
        return CommonResult.success("查询课程信息成功", map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult updateStatus(String courseId) {
        // 校验参数
        Assert.isRight(Check.isBlank(courseId), "课程id不能为空");
        // 查询是否存在该课程
        Assert.isRight(Check.isBlank(eduCourseMapper.selectById(courseId)), "课程不存在");
        // 执行修改
        EduCourse eduCourse = new EduCourse();
        eduCourse.setId(courseId);
        eduCourse.setStatus(CourseStatus.valueOf("normal").getStatus());
        Assert.isRight(eduCourseMapper.updateById(eduCourse) != 1, "课程发布失败");
        return CommonResult.success("课程发布成功");
    }

    @Override
    public CommonResult selectCourses(EduCourseQuery eduCourseQuery) {
        System.out.println(eduCourseQuery);
        // 校验参数
        Assert.isRight(Check.isBlank(eduCourseQuery), "课程查询条件异常");
        // 课程状态
        Assert.isRight(
                !(eduCourseQuery.getStatus() == null
                || "".equals(eduCourseQuery.getStatus())
                || eduCourseQuery.getStatus().equals(CourseStatus.valueOf("normal").getStatus())
                || eduCourseQuery.getStatus().equals(CourseStatus.valueOf("draft").getStatus())),
        "课程状态非法");
        // current-1
        eduCourseQuery.setCurrent((eduCourseQuery.getCurrent() - 1) * eduCourseQuery.getLimit());
        // 执行查询
        List<Map<String, Object>> list = eduCourseMapper.selectCourses(eduCourseQuery);
        Assert.isRight(Check.isBlank(list), "查询课程信息为空");
        // 封装结果集
        HashMap<String, Object> map = new HashMap<>(16);
        map.put("courses", list);
        Integer count = eduCourseMapper.selectCoursesForCount(eduCourseQuery);
        Assert.isRight(count <= 0, "查询课程信息为空");
        map.put("total", count);
        return CommonResult.success("查询课程信息成功", map);
    }

    @Override
    @Cacheable(key = "'course'", value = "courses")
    public CommonResult selectCourses() {
        // 查询前八条热门课程数据
        QueryWrapper<EduCourse> queryWrapper = new QueryWrapper<>();
        // 课程必须是已发布的课程
        queryWrapper.eq("status", CourseStatus.valueOf("normal").getStatus());
        queryWrapper.orderByDesc("view_count");
        queryWrapper.orderByDesc("buy_count");
        queryWrapper.last("limit 8");
        List<EduCourse> eduCourses = eduCourseMapper.selectList(queryWrapper);
        // 校验结果
        Assert.isRight(eduCourses == null, "查询热门课程数据有误");
        // 封装结果集
        HashMap<String, Object> map = new HashMap<>(16);
        map.put("courses", eduCourses);
        return CommonResult.success("查询热门课程数据成功", map);
    }

    @Override
    public CommonResult selectCourses(CourseVo courseVo) {
        System.out.println(courseVo);
        // 参数校验
        Assert.isRight(Check.isBlank(courseVo), "课程参数不能为空");
        // 开始查询
        QueryWrapper<EduCourse> queryWrapper = new QueryWrapper<>();
        // 讲师id
        queryWrapper.eq(Check.isNotBlank(courseVo.getTeacherId()), "teacher_id", courseVo.getTeacherId());
        // 一级课程分类
        queryWrapper.eq(Check.isNotBlank(courseVo.getSubjectParentId()), "subject_parent_id", courseVo.getSubjectParentId());
        // 二级课程分类
        queryWrapper.eq(Check.isNotBlank(courseVo.getSubjectId()), "subject_id", courseVo.getSubjectId());
        // 销量   0表示正序，1表示倒叙，下同
        if (Check.isNotBlank(courseVo.getBuyCountSort())) {
            // 正序
            if ("2".equals(courseVo.getBuyCountSort())) {
                queryWrapper.orderByAsc("buy_count");
            } else if ("1".equals(courseVo.getBuyCountSort())) {
                // 倒叙
                queryWrapper.orderByDesc("buy_count");
            }
        }
        // 时间
        if (Check.isNotBlank(courseVo.getGmtCreateSort())) {
            // 正序
            if ("2".equals(courseVo.getGmtCreateSort())) {
                queryWrapper.orderByAsc("gmt_create");
            } else if ("1".equals(courseVo.getGmtCreateSort())) {
                // 倒叙
                queryWrapper.orderByDesc("gmt_create");
            }
        }
        // 价格
        if (Check.isNotBlank(courseVo.getPriceSort())) {
            // 正序
            if ("2".equals(courseVo.getPriceSort())) {
                queryWrapper.orderByAsc("price");
            } else if ("1".equals(courseVo.getPriceSort())) {
                // 倒叙
                queryWrapper.orderByDesc("price");
            }
        }
        // 分页参数校验
        Assert.isRight(courseVo.getCurrent() == null || courseVo.getCurrent() <= 0 ||
                courseVo.getLimit() == null || courseVo.getLimit()  <= 0, "分页参数错误");
        // 执行查询
        Page<EduCourse> page = new Page<>(courseVo.getCurrent(), courseVo.getLimit());
        Page<EduCourse> coursePage = eduCourseMapper.selectPage(page, queryWrapper);
        Map<String, Object> map = new PageUtil<EduCourse>().generateMap(coursePage);
        return CommonResult.success("查询课程成功", map);
    }

    @Override
    public CommonResult selectCourseDetail(String courseId, HttpServletRequest request) {
        // 校验参数
        Assert.isRight(Check.isBlank(courseId), "课程id不能为空");
        // 查询课程详情信息
        CourseDetailVo courseDetail = eduCourseMapper.selectCourseDetail(courseId);
        Assert.isRight(Check.isBlank(courseDetail), "查询课程信息为空");
        // 查询课程的章节和小节信息，树形结构
        CommonResult commonResult = eduChapterService.selectChapters(courseId);
        // 封装结果集
        commonResult.getData().put("course", courseDetail);
        // 查询课程是否支付
        if (new BigDecimal(0).compareTo(courseDetail.getPrice()) == 0) {
            commonResult.getData().put("status", true);
            return commonResult;
        }
        // 获取用户id
        String userId = JwtUtils.getMemberIdByJwtToken(request);
        System.out.println("userId=" + userId);
        Map<String, Object> map = orderServiceClient.selectOrderStatus(courseId, userId).getData();
        System.out.println("map" + map);
        if (map != null && 1 == (Integer) map.get("status")) {
            // 已支付
            commonResult.getData().put("status", true);
            return commonResult;
        }
        commonResult.getData().put("status", false);
        return commonResult;
    }

    @Override
    public CommonResult selectCourseForOrder(String courseId) {
        // 校验参数
        Assert.isRight(Check.isBlank(courseId), "课程不能为空");
        // 执行查询
        Map<String, Object> map = eduCourseMapper.selectCourseForOrder(courseId);
        // 校验结果集
        Assert.isRight(Check.isBlank(map), "查询课程信息结果为空");
        return CommonResult.success("查询课程信息成功", map);
    }

    @Override
    public CommonResult isCourse(String courseId) {
        // 校验参数
        Assert.isRight(Check.isBlank(courseId), "课程id不能为空");
        // 查询
        EduCourse eduCourse = eduCourseMapper.selectById(courseId);
        if (eduCourse == null) {
            return CommonResult.error("课程信息不存在");
        }
        return CommonResult.success("课程存在");
    }

    @Override
    public CommonResult selectCourseById(String courseId) {
        // 校验课程是否为空
        Assert.isRight(Check.isBlank(courseId), "课程id不能为空");
        // 执行查询操作
        CourseInfoVo courseInfoVo = eduCourseMapper.selectCourseById(courseId);
        // 校验结果
        Assert.isRight(Check.isBlank(courseInfoVo), "课程不存在");
        // 封装结果集
        Map<String, Object> map = new HashMap<>(16);
        map.put("course", courseInfoVo);
        return CommonResult.success("查询课程信息成功", map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult updateCourseStatus(String[] courseIds) {
        // 校验参数
        Assert.isRight(courseIds == null || courseIds.length == 0, "课程id不能为空");
        // 校验课程状态都一致
        List<EduCourse> courses = eduCourseMapper.selectBatchIds(Arrays.asList(courseIds));
        // 若两个集合的数据长度不一致则数据出错
        Assert.isRight(courses == null || courses.size() != courseIds.length, "课程数据有误");
        String status = courses.get(0).getStatus();
        courses.stream().forEach(course -> {
            if (!status.equals(course.getStatus())) {
                // 课程状态不一致，异常处理
                Assert.isRight(true, "课程状态不一致");
            }
        });
        // 执行修改
        if (status.equals(CourseStatus.valueOf("normal").getStatus())) {
            // 课程下架
            Integer result = eduCourseMapper.updateCourseStatus(courseIds, CourseStatus.valueOf("draft").getStatus());
            Assert.isRight(courseIds.length != result, "修改课程发布状态失败");
            return CommonResult.success("修改课程发布状态成功");
        }
        // 课程发布
        Integer result = eduCourseMapper.updateCourseStatus(courseIds, CourseStatus.valueOf("normal").getStatus());
        Assert.isRight(courseIds.length != result, "修改课程发布状态失败");
        return CommonResult.success("修改课程发布状态成功");
    }

}